home *** CD-ROM | disk | FTP | other *** search
Text File | 1987-01-12 | 35.1 KB | 1,360 lines | [TEXT/PJMM] |
-
- { TransSkel version 1.02 - Transportable application skeleton}
-
- { TransSkel is public domain and was originally written in LightSpeed C by:}
-
- { Paul DuBois}
- { Wisconsin Regional Primate Research Center}
- { 1220 Capital Court}
- { Madison WI 53706 USA}
-
- { UUCP: allegra,ihnp4,seismo!uwvax!uwmacc!dubois}
- { ARPA: dubois@unix.macc.wisc.edu}
- { dubois@rhesus.primate.wisc.edu}
-
- { The Pascal Version of TransSkel is public domain and was ported by }
-
- { Owen Hartnett }
- { Ωhm Software }
- { 163 Richard Drive }
- { Tiverton, RI 02878 }
-
- { CSNET: omh@cs.brown.edu.CSNET }
- { ARPA: omh%cs.brown.edu@relay.cs.net-relay.ARPA }
- { UUCP: [ihnp4,allegra]!brunix !omh }
-
- { Psychic Wavelength: 182.2245 Meters (sorry, couldn't resist) }
-
- { This version of TransSkel written for Lightspeed Pascal. Lightspeed Pascal is a}
- { trademark of:}
- { THINK Technologies, Inc}
- { 420 Bedford Street Suite 350}
- { Lexington, MA 02173 USA}
-
- { History}
- { 06/13/86 Beta version.}
- { 08/27/86 Version number changed to 1.01.}
- { v1.0 DoGrow bug fixed - the port at the point of the}
- { InvalRect could have been anything; the fix is to set}
- { the port to the grown window first. This also explains}
- { why the kludge to DoActivate in v1.0 worked.}
- { 10/02/86 Version number changed to 1.02, as a result of adding}
- { modifications by David W. Berry (well!dwb@lll-lcc.arpa)}
- { for supporting window zooming. Also used his modifications}
- { for supporting modeless dialogs (though not in the same}
- { form). Dialogs can be #define'd on or off.}
- { 12/24/86 Finished final debugging of Pascal version. (well, final as they }
- { come.) Dialogs cannot be defined off. Santa Claus assists with final }
- { modification.}
-
- UNIT TransSkelpas;
-
- INTERFACE
-
- PROCEDURE SkelInit;
- PROCEDURE SkelMain;
- PROCEDURE SkelWhoa;
- PROCEDURE SkelClobber;
- PROCEDURE SkelMenu (theMenu : MenuHandle;
- pSelect : ProcPtr;
- pClobber : ProcPtr);
- PROCEDURE SkelRmveMenu (theMenu : MenuHandle);
- PROCEDURE SkelApple (aboutTitle : Str255;
- aboutProc : ProcPtr);
- PROCEDURE SkelWindow (theWind : WindowPtr;
- pMouse, pKey, pUpdate, pActivate, pClose, pClobber, pIdle : ProcPtr;
- frontOnly : Boolean);
- PROCEDURE SkelRmveWind (theWind : WindowPtr);
- PROCEDURE SkelDialog (theDialog : DialogPtr;
- pEvent, pClose, pClobber : ProcPtr);
- PROCEDURE SkelRmveDlog (theDialog : DialogPtr);
- PROCEDURE SkelGrowBounds (theWind : WindowPtr;
- hLO, vLo, hHi, vHi : integer);
- PROCEDURE SkelEventMask (mask : integer);
- PROCEDURE SkelGetEventMask (mask : integer);
- PROCEDURE SkelBackground (p : ProcPtr);
- PROCEDURE SkelGetBackground (VAR p : ProcPtr);
- PROCEDURE SkelEventHook (p : ProcPtr);
- PROCEDURE SkelGetEventHook (VAR p : ProcPtr);
- PROCEDURE SkelDlogMask (mask : integer);
- PROCEDURE SkelGetDlogMask (VAR mask : integer);
-
-
-
- IMPLEMENTATION
- CONST
- mBarHeight = 20; { menu bar height. All window sizing}
-
- { This window zooming stuff may need to be removed if you use the new Rom libraries }
- { if not, then you can add zooming without the overhead of the new Rom libs. See TrackBox }
- { routine also. }
-
- inZoomIn = 7;
- inZoomOut = 8;
- { Window and Menu handler types, constants, variables.}
-
- { whList and mhList are the lists of window and menu handlers.}
- { whClobOnRmve and mhClobOnRmve are true if the handler disposal proc}
- { is to be called when a handler is removed. They are temporarily set}
- { false when handlers are installed for windows or menus that already}
- { have handlers - the old handler is removed WITHOUT calling the}
- { disposal proc.}
-
- { Default lower limits on window sizing of 80 pixels both directions is}
- { sufficient to allow text windows room to draw a grow box and scroll}
- { bars without having the thumb and arrows overlap. These values may}
- { be changed if such a constraint is undesirable with SkelGrowBounds.}
- { Default upper limits are for the Macintosh, not the Lisa, but are set}
- { per machine in SkelInit.}
-
- TYPE
- WHandlerPtr = ^WHandler;
- WHandlerHnd = ^WHandlerPtr;
- WHandler = RECORD
- whWind : WindowPtr; {window/dialog to be handled }
- whClobber : ProcPtr; { data structure disposal proc }
- whMouse : ProcPtr; { mouse-click handler proc }
- whKey : ProcPtr; { key-click handler proc }
- whUpdate : ProcPtr; { update handler proc }
- whActivate : ProcPtr; { activate event handler proc }
- whClose : ProcPtr; { close "event" handler proc }
- whIdle : ProcPtr; { main loop proc }
- whEvent : ProcPtr; { dialog event proc }
- whGrow : Rect; { limits on window sizing }
- whSized : Boolean; { true = window was resized }
- whFrontOnly : Boolean; { true = idle only when active }
- whNext : WHandlerHnd; { next window handler }
- END;
-
- MHandlerPtr = ^MHandler;
- MHandlerHnd = ^MHandlerPtr;
-
- MHandler = RECORD
- mhID : integer; { menu id }
- mhSelect : ProcPtr; { item selection handler proc }
- mhClobber : ProcPtr; { menu disposal handler proc }
- mhNext : MHandlerHnd; { next menu handler }
- END;
-
- EventPtr = ^EventRecord;
- VAR
- whList : WHandlerHnd; { list of menu handlers }
- whClobOnRmve : Boolean;
- growRect : Rect;
- mhList : MHandlerHnd;
- mhClobOnRmve : Boolean;
-
- { Variables for default Apple menu handler. appleID is set to 1 if}
- { SkelApple is called and is the id of the Apple menu, appleAboutProc}
- { is the procedure to execute if there is an About... item and it's}
- { chosen from the Apple menu. If doAbout is true, then the menu}
- { contains the About... item, otherwise it's just desk accessories.}
-
- appleMenu : MenuHandle;
- appleID : integer;
- appleAboutProc : ProcPtr;
- doAbout : Boolean;
-
- { Miscellaneous}
-
- { screenPort points to the window manager port.}
-
- { doneFlag determines when SkelMain returns. It is set by calling}
- { SkelWhoa(), which the host does to request a halt.}
-
- { pBkgnd points to a background procedure, to be run during event}
- { processing. Set it with SkelBackground. If nil, there's no}
- { procedure.}
-
- { pEvent points to an event-inspecting hook, to be run whenever an}
- { event occurs. Set it with SkelEventHook. If nil, there's no}
- { procedure.}
-
- { eventMask controls the event types requested in the GetNextEvent}
- { call in SkelMain.}
-
- { diskInitPt is the location at which the disk initialization dialog}
- { appears, if an uninitialized disk is inserted.}
-
- screenPort : GrafPtr;
- doneFlag : integer;
- pBkgnd : ProcPtr;
- pEvent : ProcPtr;
- eventMask : integer;
- diskInitPt : Point;
-
- { Events that are passed to dialogs. Others are ignored.}
- { Standard mask passes , mousedown, keydown, autokey, update,}
- { activate and null events. Null events are controlled by bit 0.}
-
- dlogEventMask : integer;
- pEventflag : Boolean;
-
- { Rather than including the entire new ROM libraries, with all the other stuff you might not use }
- { I've instead included just the Zoom box stuff here. Depending on your status, you can either }
- { leave things as they are, and only use zooming from the new Rom libs, or comment out the }
- { calls, and include the new Rom libraries if you want to incorporate other new Rom calls }
-
- FUNCTION TrackBox (theWindow : WindowPtr;
- thePt : Point;
- partCode : INTEGER) : BOOLEAN;
- INLINE
- $A83B;
-
- { -------------------------------------------------------------------- }
- { Internal (private) Routines }
- { -------------------------------------------------------------------- }
-
-
-
- { Get handler associated with user or dialog window.}
- { Return nil if window doesn't belong to any known handler.}
- { This routine is absolutely fundamental to TransSkel.}
-
- FUNCTION GetWDHandler (theWind : WindowPtr) : WHandlerHnd;
-
- VAR
- h : WHandlerHnd;
- BEGIN
- h := WhList;
- GetWDHandler := NIL;
- WHILE h <> NIL DO
- IF h^^.whWind = theWind THEN
- BEGIN
- GetWDHandler := h;
- h := NIL;
- END
- ELSE
- h := WHandlerHnd(h^^.whNext);
- END;
-
- FUNCTION GetWHandler (theWind : WindowPtr) : WHandlerHnd;
-
- VAR
- h : WHandlerHnd;
- myPeek : WindowPeek;
-
- BEGIN
- h := GetWDHandler(theWind);
- myPeek := WindowPeek(theWind);
- IF h <> NIL THEN
- BEGIN
- IF mypeek^.windowKind <> dialogKind THEN
- GetWHandler := h;
- END
- ELSE
- GetWHandler := NIL;
- END;
-
- { Get handler associated with dialog window.}
- { Return nil if window doesn't belong to any known handler.}
- { The order of the two tests is critical: theDialog might be nil.}
-
- FUNCTION GetDHandler (theDialog : WindowPtr) : WHandlerHnd;
-
- VAR
- h : WHandlerHnd;
- myPeek : WindowPeek;
-
- BEGIN
- h := GetWDHandler(theDialog);
- myPeek := WindowPeek(theDialog);
- IF h <> NIL THEN
- BEGIN
- IF mypeek^.windowKind = dialogKind THEN
- GetDHandler := h;
- END
- ELSE
- GetDHandler := NIL;
- END;
-
- {The following procedures are Pascal "glue" that allows Pascal to call a Procedure }
- { from a ProcPtr. It is similar to (*p) () construct used in the C dialect. Different }
- { procedures are necessary for the reason of Pascal's strongly typed parameter }
- { list. Fortunately, there are not too many calls which use different param lists }
-
- PROCEDURE callpMouse (thePoint : Point;
- theTime : longint;
- theMods : integer;
- myProc : ProcPtr);
-
- INLINE
- $205f, {movea.l (a7)+,a0 ; (a0) is a ptr to string, 4(a0) is mode}
- $4e90;
-
- PROCEDURE callpKey (theChar : char;
- theMods : integer;
- myProc : ProcPtr);
-
- INLINE
- $205f, {movea.l (a7)+,a0 ; (a0) is a ptr to string, 4(a0) is mode}
- $4e90;
-
- PROCEDURE callpEvent (theitem : integer;
- theEvent : EventPtr;
- myProc : ProcPtr);
-
- INLINE
- $205f, {movea.l (a7)+,a0 ; (a0) is a ptr to string, 4(a0) is mode}
- $4e90;
-
- FUNCTION callotherEvent (theEvent : EventPtr;
- myProc : ProcPtr) : Boolean;
-
- INLINE
- $205f, $4e90;
-
-
- PROCEDURE callpBoolean (myBool : Boolean;
- myProc : ProcPtr);
-
- { Two calls use Booleans as one parameter arguments. This procedure handles }
- { both of them. }
-
- INLINE
- $205f, {movea.l (a7)+,a0 ; (a0) is a ptr to string, 4(a0) is mode}
- $4e90;
-
- PROCEDURE callpInt (myInt : integer;
- myProc : ProcPtr);
-
- { Two calls use Booleans as one parameter arguments. This procedure handles }
- { both of them. }
-
- INLINE
- $205f, {movea.l (a7)+,a0 ; (a0) is a ptr to string, 4(a0) is mode}
- $4e90;
-
- PROCEDURE callpMenu (myMenu : MenuHandle;
- myProc : ProcPtr);
-
- { Handle removeal of menus. }
-
- INLINE
- $205f, {movea.l (a7)+,a0 ; (a0) is a ptr to string, 4(a0) is mode}
- $4e90;
-
- PROCEDURE callpnoarg (myProc : ProcPtr);
-
- { For all the Procedures that are called with no arguments }
-
- INLINE
- $205f, {movea.l (a7)+,a0 ; (a0) is a ptr to string, 4(a0) is mode}
- $4e90;
-
- { General menu-handler. Just passes selection to the handler's}
- { select routine. If the select routine is nil, selecting items from}
- { the menu is a nop.}
-
- PROCEDURE DoMenuCommand (command : longint);
-
- VAR
- menu : integer;
- item : integer;
- mh : MHandlerHnd;
- p : ProcPtr;
-
- BEGIN
- menu := HiWord(command);
- item := LoWord(command);
- mh := mhList;
- WHILE (mh <> NIL) DO
- BEGIN
- p := mh^^.mhSelect;
- IF ((menu = mh^^.mhID) AND (p <> NIL)) THEN
- BEGIN
- callpInt(item, p);
- mh := NIL;
- END
- ELSE
- mh := mh^^.mhNext;
- END;
- HiliteMenu(0);
- END;
-
- { Apple menu handler}
-
- { DoAppleItem: If the first item was chosen, and there's an "About..."}
- { item, call the procedure associated with it (if not nil). If there}
- { is no "About..." item or the item was not the first one, then open}
- { the associated desk accessory. The port is saved and restored}
- { because OpenDeskAcc does not always preserve it correctly.}
-
- { DoAppleClobber disposes of the Apple menu.}
-
- PROCEDURE DoAppleItem (item : integer);
-
- VAR
- curPort : GrafPtr;
- str : Str255;
- ignore : integer;
-
- BEGIN
- IF doAbout AND (item = 1) THEN
- BEGIN
- IF appleAboutProc <> NIL THEN
- callpnoarg(appleAboutProc);
- END
- ELSE
- BEGIN
- GetPort(curPort);
- GetItem(appleMenu, item, str);
- ignore := OpenDeskAcc(str);
- SetPort(curPort);
- END;
- END;
-
- PROCEDURE DoAppleClobber;
- BEGIN
- DisposeMenu(appleMenu);
- END;
-
- { -------------------------------------------------------------------- }
- { Window-handler routing routines }
- { }
- { Each routine sets the port to the handler's window before executing }
- { the handler procedure. }
- { -------------------------------------------------------------------- }
-
-
- { Pass local mouse coordinates, click time, and the modifiers flag}
- { word to the handler.}
-
- PROCEDURE DoMouse (h : WHandlerHnd;
- theEvent : EventPtr);
-
- VAR
- p : ProcPtr;
- thePt : Point;
-
- BEGIN
- IF (h <> NIL) THEN
- BEGIN
- SetPort(h^^.whWind);
- p := h^^.whMouse;
- IF p <> NIL THEN
- BEGIN
- thePt := theEvent^.where;
- GlobalToLocal(thePt);
- callpMouse(thePt, theEvent^.when, theEvent^.modifiers, p);
- END;
- END;
- END;
-
- { Pass the character and the modifiers flag word to the handler.}
-
- PROCEDURE DoKey (h : WHandlerHnd;
- ch : char;
- mods : integer);
- VAR
- p : ProcPtr;
-
- BEGIN
- IF h <> NIL THEN
- BEGIN
- SetPort(h^^.whWind);
- p := h^^.whKey;
- IF p <> NIL THEN
- callpKey(ch, mods, p);
- END;
- END;
-
- PROCEDURE DoUpdate (h : WHandlerHnd);
-
- VAR
- rh : WhandlerHnd;
- p : ProcPtr;
- updPort, tmpPort : GrafPtr;
-
- BEGIN
- rh := h;
- IF rh <> NIL THEN
- BEGIN
- GetPort(tmpPort);
- updPort := rh^^.whWind;
- SetPort(updPort);
- BeginUpdate(updPort);
- p := rh^^.whUpdate;
- IF p <> NIL THEN
- BEGIN
- callpBoolean(rh^^.whSized, p);
- rh^^.whSized := false;
- END;
- EndUpdate(updPort);
- SetPort(tmpPort);
- END;
- END;
-
- PROCEDURE DoActivate (h : WHandlerHnd;
- active : Boolean);
-
- VAR
- p : ProcPtr;
-
- BEGIN
- IF h <> NIL THEN
- p := h^^.whActivate
- ELSE
- p := NIL;
- IF (h <> NIL) AND (p <> NIL) THEN
- BEGIN
- SetPort(h^^.whWind);
- callpBoolean(active, p);
- END;
- END;
-
- { Execute a window handler's close proc. This may be used by handlers}
- { for temp windows that want to remove themselves when the window}
- { is closed: they can call SkelRmveWind to dispose of the window}
- { and remove the handler from the window handler list. Thus, windows}
- { may be dynamically created and destroyed without filling up the}
- { handler list with a bunch of invalid handlers.}
-
- { If the handler doesn't have a close proc, just hide the window.}
- { The host should provide some way of reopening the window (perhaps}
- { a menu selection). Otherwise the window will be lost from user}
- { control if it is hidden, since it won't receive user events.}
-
- { The port is set to the window manager port after calling the}
- { handler proc, to avoid a dangling port.}
-
- { This is called both for regular and dialog windows.}
-
- PROCEDURE DoClose (h : WHandlerHnd);
-
- VAR
- rh : WHandlerHnd;
- p : ProcPtr;
- BEGIN
- rh := h;
- IF rh <> NIL THEN
- BEGIN
- SetPort(rh^^.whWind);
- p := rh^^.whClose;
- IF (p <> NIL) THEN
- callpnoarg(p)
- ELSE
- HideWindow(rh^^.whWind);
- SetPort(screenPort);
- END;
- END;
-
- PROCEDURE DoClobber (h : WHandlerHnd);
-
- VAR
- p : ProcPtr;
- BEGIN
- IF (h <> NIL) THEN
- BEGIN
- SetPort(h^^.whWind);
- p := h^^.whClobber;
- IF p <> NIL THEN
- callpnoarg(p);
- SetPort(screenPort);
- END;
- END;
-
- PROCEDURE DoIdle (h : WHandlerHnd);
-
- VAR
- p : ProcPtr;
- tmpPort : GrafPtr;
- BEGIN
- IF (h <> NIL) THEN
- BEGIN
- GetPort(tmpPort);
- SetPort(h^^.whWind);
- p := h^^.whIdle;
- IF (p <> NIL) THEN
- callpnoarg(p);
- SetPort(tmpPort);
- END;
- END;
-
-
- { Handle event if it's for a dialog. The event must be one of}
- { those that is passed to dialogs according to dlogEventMask.}
- { This mask can be set so that disk-inserts, for instance, don't}
- { get eaten up.}
-
- FUNCTION DoDialog (theEvent : EventPtr) : Boolean;
-
- VAR
- dh : WHandlerHnd;
- theDialog : DialogPtr;
- what : integer;
- item : integer;
- tmpPort : GrafPtr;
- ignore : Boolean;
- testme : longint;
-
- BEGIN
-
- { handle command keys before they get to IsDialogEvent}
-
- what := theEvent^.what;
- testme := BitShift(longint(1), what);
- testme := BitAnd(testme, longint(dlogEventMask));
- IF (((what = keydown) OR (what = autokey)) AND Boolean(BitAnd(theEvent^.modifiers, cmdkey))) THEN
- BEGIN
- DoMenuCommand(MenuKey(Char(BitAnd(theEvent^.message, charCodeMask))));
- DoDialog := true;
- END
- ELSE IF testme > 0 THEN
-
- IF IsDialogEvent(theEvent^) THEN
- BEGIN
- IF DialogSelect(theEvent^, theDialog, item) THEN
- BEGIN
- dh := WHandlerHnd(GetDHandler(theDialog));
- IF (dh <> NIL) THEN
- IF (dh^^.whEvent <> NIL) THEN
- BEGIN
- GetPort(tmpPort);
- SetPort(theDialog);
- callpEvent(item, theEvent, dh^^.whEvent);
- SetPort(tmpPort);
- END;
- END;
- DoDialog := true;
- END
- ELSE
- DoDialog := false;
- END;
-
-
- { -------------------------------------------------------------------- }
- { Event-handling routines }
- { -------------------------------------------------------------------- }
-
- { Have either sized or zoomed the window. Invalidate it to force}
- { an update and set the 'resized' flag in the window handler true.}
-
- PROCEDURE TriggerUpdate (h : WHandlerHnd;
- thePort : GrafPtr);
-
- BEGIN
- SetPort(thePort);
- InvalRect(thePort^.portRect);
- IF (h <> NIL) THEN
- BEGIN
- h^^.whSized := true;
- END;
- END;
-
- { Size a window. If the window has a handler, use the grow limits}
- { in the handler record, otherwise use the defaults.}
-
- { The portRect is invalidated to force an update event. (The port}
- { must be set first, as it could be pointing anywhere.) The handler's}
- { update procedure should check the parameter passed to it to check}
- { whether the window has changed size, if it needs to adjust itself to}
- { the new size. THIS IS A CONVENTION. Update procs must notice grow}
- { "events", there is no procedure specifically for such events.}
-
- { The clipping rectangle is not reset. If the host application}
- { keeps the clipping set equal to the portRect or something similar,}
- { then it will have to arrange to treat window growing with more}
- { care.}
-
- PROCEDURE DoGrow (h : WHandlerHnd;
- thePort : GrafPtr;
- StartPt : Point);
-
- VAR
- r : Rect;
- growRes : longint;
-
- BEGIN
- IF (h <> NIL) THEN
- BEGIN
- r := h^^.whGrow;
- END
- ELSE
- r := growRect;
- growRes := GrowWindow(thePort, startPt, r);
- IF growRes <> 0 THEN
- BEGIN
- SizeWindow(thePort, LoWord(growRes), HiWord(growRes), false);
- TriggerUpdate(h, thePort);
- END;
- END;
-
- { Remove following procedure if using new rom library }
-
- PROCEDURE ZoomWindow (theWindow : GrafPtr;
- partCode : INTEGER;
- front : BOOLEAN);
- INLINE
- $A83A;
-
- { Zoom the current window. Very similar to DoGrow}
-
- PROCEDURE DoZoom (h : WHandlerHnd;
- thePort : GrafPtr;
- partcode : integer);
-
- BEGIN
- ZoomWindow(thePort, partcode, false);
- TriggerUpdate(h, thePort);
- END;
-
- { General event handler}
-
- PROCEDURE DoEvent (theEvt : EventPtr);
-
- VAR
- theEvent : EventPtr;
- evtPt : Point;
- evtPort : GrafPtr;
- evtPart : integer;
- evtChar : char;
- evtMods : integer;
- h : WHandlerHnd;
- r : Rect;
- ignore : integer;
-
- BEGIN
- theEvent := theEvt;
- IF (DoDialog(theEvent)) THEN
- BEGIN
- END
- ELSE
- BEGIN
- evtPt := theEvent^.where;
- CASE theEvent^.what OF
- nullEvent :
- ;
-
- { Mouse click. Get the window that the click occurred in, and the}
- { part of the window.}
-
- mouseDown :
- BEGIN
- evtPart := FindWindow(evtPt, evtPort);
- h := GetWHandler(evtPort);
- CASE evtPart OF
-
- { Click in a desk accessory window. Pass back to the system.}
-
- inSysWindow :
- SystemClick(theEvent^, evtPort);
-
- { Click in menu bar. Track the mouse and execute selected command,}
- { if any.}
-
- inMenuBar :
- DoMenuCommand(MenuSelect(evtPt));
-
- { Click in grow box. Resize window.}
-
- inGrow :
- DoGrow(h, evtPort, evtPt);
-
- { Click in title bar. Drag the window around. Leave at least}
- { 4 pixels visible in both directions.}
-
- inDrag :
- BEGIN
- r := screenPort^.portRect;
- r.top := r.top + mBarHeight; { Skip down past menu bar }
- InsetRect(r, 4, 4);
- DragWindow(evtPort, evtPt, r);
- END;
-
- { Click in close box. Call the close proc if the window has one.}
-
- inGoAway :
- IF (TrackGoAway(evtPort, evtPt)) THEN
- DoClose(GetWDHandler(evtPort));
-
- { Click in content region. If the window wasn't frontmost (active),}
- { just select it, otherwise pass the click to the window's mouse}
- { click handler.}
-
- inContent :
- IF (evtPort <> FrontWindow) THEN
- SelectWindow(evtPort)
- ELSE
- DoMouse(h, theEvent);
-
- { Click in zoom box. Track the click and then zoom the window if}
- { necessary}
-
- inZoomin, inZoomOut :
- IF (TrackBox(evtPort, evtPt, evtPart)) THEN
- DoZoom(h, evtport, evtPart);
- OTHERWISE
- ;
- END;{mousedown}
- END;
-
- { Key event. If the command key was down, process as menu item}
- { selection, otherwise pass the character and the modifiers flags}
- { to the active window's key handler.}
-
- { If dialogs are supported, there's no check for command-key}
- { equivalents, since that would have been checked in DoDialog.}
-
- keydown, autokey :
- BEGIN
- evtChar := char(BitAnd(theEvent^.message, charCodeMask));
- evtMods := theEvent^.modifiers;
- IF BitAnd(evtMods, cmdKey) > 0 THEN
- DoMenuCommand(menuKey(evtChar))
- ELSE
- DoKey(GetWHandler(FrontWindow), evtChar, evtMods);
- END;
-
- { Update a window.}
-
- updateEvt :
- DoUpdate(GetWHandler(WindowPtr(theEvent^.message)));
-
- { Activate or deactivate a window.}
-
- activateEvt :
- DoActivate(GetWHandler(WindowPtr(theEvent^.message)), (BitAnd(theEvent^.modifiers, activeFlag) <> 0));
-
- { handle inserts of uninitialized disks}
-
- diskEvt :
- IF (HiWord(theEvent^.message) <> noErr) THEN
- BEGIN
- DILoad;
- ignore := DIBadMount(diskInitPt, theEvent^.message);
- DIUnload;
- END;
- OTHERWISE
- END;
- END;
- END;
-
- { -------------------------------------------------------------------- }
- { Interface (public) Routines }
- { -------------------------------------------------------------------- }
-
-
- { Initialize the various Macintosh Managers.}
- { Set default upper limits on window sizing.}
- { FlushEvents does NOT toss disk insert events, so that disks}
- { inserted while the application is starting up don't result}
- { in dead drives.}
-
- PROCEDURE SkelInit;
- BEGIN
- InitCursor;
- whList := NIL;
- whClobOnRmve := true;
- SetRect(growRect, 80, 80, 512, 342 - mBarHeight);
- mhList := NIL;
- mhClobOnRmve := true;
- appleID := 0;
- appleAboutProc := NIL;
- doAbout := false;
- doneflag := 0;
- pBkgnd := NIL;
- pEvent := NIL;
- pEventflag := false;
- eventmask := everyEvent;
- diskInitPt.v := 120;
- diskInitPt.h := 100;
- dlogEventMask := $16b;
-
- { Set upper limits of window sizing to machine screen size. Allow}
- { for the menu bar.}
-
- GetWMgrPort(screenport);
- growRect.right := screenPort^.portRect.right;
- growRect.bottom := screenPort^.portRect.bottom - mBarHeight;
- END;
-
- { Main loop.}
-
- { Task care of DA's with SystemTask.}
- { Run background task if there is one.}
- { If there is an event, check for an event hook. If there isn't}
- { one defined, or if there is but it returns false, call the}
- { general event handler. (Hook returns true if TransSkel should}
- { ignore the event.)}
- { If no event, call the "no-event" handler for the front window and for}
- { any other windows with idle procedures that are always supposed}
- { to run. This is done in such a way that it is safe for idle procs}
- { to remove the handler for their own window if they want (unlikely,}
- { but...) This loop doesn't check whether the window is really}
- { a dialog window or not, but it doesn't have to, because such}
- { things always have a nil idle proc.}
- { }
- { doneFlag is reset upon exit. This allows it to be called}
- { repeatedly, or recursively.}
-
- { If dialogs are supported, null events are looked at (in SkelMain)}
- { and passed to the event handler. This is necessary to make sure}
- { DialogSelect gets called repeatedly, or the caret won't blink if}
- { a dialog has any editText items.}
-
- { If an event-inspecting hook is installed, null events are not passed}
- { to it.}
-
- PROCEDURE SkelMain;
-
- VAR
- theEvent : EventRecord;
- wh, wh2 : WHandlerHnd;
- w : WindowPtr;
- haveEvent, testpevent, testbool : Boolean;
-
- BEGIN
- WHILE (doneFlag = 0) DO
- BEGIN
- SystemTask;
- IF (pBkgnd <> NIL) THEN
- callpnoarg(pBkgnd);
- haveEvent := GetNextEvent(eventMask, theEvent);
- IF (pEvent <> NIL) THEN
- testpevent := CallotherEvent(@theEvent, pEvent)
- ELSE
- testpevent := false;
- testbool := haveEvent AND (testpevent = false);
- IF ((pEvent = NIL) OR testbool) THEN
- DoEvent(@theEvent);
- IF NOT haveEvent THEN
- BEGIN
- wh := whList;
- WHILE (wh <> NIL) DO
- BEGIN
- wh2 := wh^^.whNext;
- w := wh^^.whWind;
- IF ((w = FrontWindow) OR NOT wh^^.whFrontOnly) THEN
- BEGIN
- SystemTask;
- DoIdle(wh);
- END;
- wh := wh2;
- END;
- END;
- END;
- doneFlag := 0;
- END;
-
- { Tell SkelMain to stop}
-
- PROCEDURE SkelWhoa;
- BEGIN
- doneFlag := 1;
- END;
-
- { Clobber all the menu, window and dialog handlers}
-
- PROCEDURE SkelClobber;
-
-
- BEGIN
- WHILE (whList <> NIL) DO
- BEGIN
- SkelRmveWind(whList^^.whWind);
- END;
- WHILE (mhList <> NIL) DO
- BEGIN
- SkelRmveMenu(GetMHandle(mhList^^.mhID));
- END;
- END;
-
- { -------------------------------------------------------------------- }
- { Menu-handler interface routines }
- { -------------------------------------------------------------------- }
-
-
-
-
- { Install handler for a menu. Remove any previous handler for it.}
- { Pass the following parameters:}
-
- { theMenu Handle to the menu to be handled. Must be created by host.}
- { pSelect Proc that handles selection of items from menu. If this is}
- { nil, the menu is installed, but nothing happens when items}
- { are selected from it.}
- { pClobber Proc for disposal of handler's data structures. Usually}
- { nil for menus that remain in menu bar until program}
- { termination.}
-
- { The menu is installed and drawn in the menu bar.}
-
- PROCEDURE SkelMenu;
- VAR
- mh : MHandlerHnd;
- myHand : Handle;
- BEGIN
- mhClobOnRmve := false;
- SkelRmveMenu(theMenu);
- mhClobOnRmve := true;
- myHand := NewHandle(Sizeof(MHandler));
-
- mh := MHandlerHnd(myHand);
- mh^^.mhNext := mhList;
- mhList := MHandlerHnd(myHand);
- mh^^.mhID := theMenu^^.menuID; { get menu id number }
- mh^^.mhSelect := pSelect; { install selection handler }
- mh^^.mhClobber := pClobber; { install disposal handler }
- InsertMenu(theMenu, 0); { put menu at end of menu bar }
- DrawMenuBar;
- END;
-
- { Remove a menu handler. This calls the handler's disposal routine}
- { and then takes the handler out of the handler list and disposes}
- { of it.}
-
- { Note that the menu MUST be deleted from the menu bar before calling}
- { the clobber proc, because the menu bar will end up filled with}
- { garbage if the menu was allocated with NewMenu (see discussion of}
- { DisposeMenu in Menu Manager section of Inside Macintosh).}
-
- PROCEDURE SkelRmveMenu;
-
- VAR
- mID : integer;
- h, h2 : MHandlerHnd;
- p : ProcPtr;
- returnflag : Boolean;
-
- BEGIN
- mID := theMenu^^.menuID;
- returnflag := false;
- IF mhlist <> NIL THEN
- BEGIN
- IF mhList^^.mhID = mID THEN
- BEGIN
- h2 := mhlist;
- mhList := h2^^.mhNext;
- END
- ELSE
- BEGIN
- h := mhList;
- WHILE (h <> NIL) AND NOT returnflag DO
- BEGIN
- h2 := h^^.mhNext;
- IF (h2 = NIL) THEN
- BEGIN
- h := NIL;
- returnflag := true;
- END
- ELSE IF h2^^.mhID = mID THEN
- BEGIN
- h^^.mhNext := h2^^.mhNext;
- h := NIL;
- END;
- IF h <> NIL THEN
- h := h2;
- END;
- END;
- IF NOT returnflag THEN
- BEGIN
- DeleteMenu(mID);
- DrawMenuBar;
- p := h2^^.mhClobber;
- IF mhClobOnRmve AND (p <> NIL) THEN
- callpMenu(theMenu, p);
- DisposHandle(Handle(h2));
- END;
- END;
- END;
-
- { Install a handler for the Apple menu.}
-
- { SkelApple is called if TransSkel is supposed to handle the apple}
- { menu itself. The title is the title of the first item. If nil,}
- { then only desk accessories are put into the menu. If not nil, then}
- { the title is entered as the first item, followed by a gray line,}
- { then the desk accessories.}
-
-
- PROCEDURE SkelApple;
-
- VAR
- appleTitle : Str255;
-
- BEGIN
- appleTitle := ' ';
- appleTitle[1] := char($14);
- appleID := 1;
- AppleMenu := NewMenu(appleID, appleTitle);
- IF aboutTitle <> '' THEN
- BEGIN
- doAbout := true;
- AppendMenu(appleMenu, aboutTitle);
- AppendMenu(appleMenu, '(-');
- AppleAboutProc := aboutProc;
- END;
- AddResMenu(appleMenu, 'DRVR');
- SkelMenu(appleMenu, @DoAppleItem, @DoAppleClobber);
- END;
-
- { -------------------------------------------------------------------- }
- { Window-handler interface routines }
- { -------------------------------------------------------------------- }
-
-
-
- { Install handler for a window. Remove any previous handler for it.}
- { Pass the following parameters:}
-
- { theWind Pointer to the window to be handled. Must be created by host.}
- { pMouse Proc to handle mouse clicks in window. The proc will be}
- { passed the point (in local coordinates), the time of the}
- { click, and the modifier flags word.}
- { pKey Proc to handle key clicks in window. The proc will be passed}
- { the character and the modifier flags word.}
- { pUpdate Proc for updating window. TransSkel brackets calls to update}
- { procs with calls to BeginUpdate and EndUpdate, so the visRgn}
- { is set up correctly. A flag is passed indicating whether the}
- { window was resized or not. BY CONVENTION, the entire portRect}
- { is invalidated when the window is resized. That way, the}
- { handler's update proc can redraw the entire content region}
- { without interference from BeginUpdate/EndUpdate. The flag}
- { is set to false after the update proc is called; the}
- { assumption is made that it will notice the resizing and}
- { respond appropriately.}
- { pActivate Proc to execute when window is activated or deactivated.}
- { A boolean is passed to it which is true if the window is}
- { coming active, false if it's going inactive.}
- { pClose Proc to execute when mouse clicked in close box. Useful}
- { mainly to temp window handlers that want to know when to}
- { self-destruct (with SkelRmveWind).}
- { pClobber Proc for disposal of handler's data structures}
- { pIdle Proc to execute when no events are pending.}
- { frontOnly True if pIdle should execute on no events only when}
- { theWind is frontmost, false if executes all the time. Note}
- { that if it always goes, everything else may be slowed down!}
-
- { If a particular procedure is not needed (e.g., key events are}
- { not processed by a handler), pass nil in place of the appropriate}
- { procedure address.}
-
- { All handler procedures may assume that the port is set correctly}
- { at the time they are called.}
-
- PROCEDURE SkelWindow;
-
- VAR
- hHand : WhandlerHnd;
-
- BEGIN
- whClobOnRmve := false;
- SkelRmveWind(theWind);
- whClobOnRmve := true;
-
- hHand := WHandlerHnd(NewHandle(Sizeof(WHandler)));
- hHand^^.whNext := whList;
- whList := hHand;
- WITH hHand^^ DO
- BEGIN
- whWind := theWind;
- whMouse := pMouse;
- whKey := pKey;
- whUpdate := pUpdate;
- whActivate := pActivate;
- whClose := pClose;
- whClobber := pClobber;
- whIdle := pIdle;
- whFrontOnly := frontOnly;
- whSized := false;
- whGrow := GrowRect;
- END;
- SetPort(theWind);
- END;
-
- { Remove a window handler. This calls the handler's disposal routine}
- { and then takes the handler out of the handler list and disposes}
- { of it.}
-
- { SkelRmveWind is also called by SkelRmveDlog.}
-
- PROCEDURE SkelRmveWind;
-
- VAR
- h, h2 : WHandlerHnd;
- returnflag : Boolean;
-
- BEGIN
- IF (whList <> NIL) THEN
- BEGIN
- returnflag := false;
- IF whList^^.whWind = theWind THEN
- BEGIN
- h2 := whlist;
- whList := whList^^.whNext;
- END
- ELSE
- BEGIN
- h := whList;
- WHILE (h <> NIL) AND NOT returnflag DO
- BEGIN
- h2 := h^^.whNext;
- IF (h2 = NIL) THEN
- BEGIN
- h := NIL;
- returnflag := true;
- END
- ELSE IF h2^^.whWind = theWind THEN
- BEGIN
- h^^.whNext := h2^^.whNext;
- h := NIL;
- END;
- IF h <> NIL THEN
- h := h2;
- END;
- END;
- IF NOT returnflag THEN
- BEGIN
- IF (whClobOnRmve) THEN
- DoClobber(h2);
- DisposHandle(Handle(h2));
- END;
- END;
- END;
-
- { -------------------------------------------------------------------- }
- { Dialog-handler interface routines }
- { -------------------------------------------------------------------- }
-
-
-
- { Install a dialog handler. Remove any previous handler for it.}
- { SkelDialog calls SkelWindow as a subsidiary to install a window}
- { handler, then sets the event procedure on return.}
-
- { Pass the following parameters:}
-
- { theDialog Pointer to the dialog to be handled. Must be created}
- { by host.}
- { pEvent Event-handling proc for dialog events.}
- { pClose Proc to execute when mouse clicked in close box. Useful}
- { mainly to dialog handlers that want to know when to}
- { self-destruct (with SkelRmveDlog).}
- { pClobber Proc for disposal of handler's data structures}
-
- { If a particular procedure is not needed, pass nil in place of}
- { the appropriate procedure address.}
-
- { All handler procedures may assume that the port is set correctly}
- { at the time they are called.}
-
- PROCEDURE SkelDialog;
-
- VAR
- wh : WHandlerHnd;
-
- BEGIN
- SkelWindow(theDialog, NIL, NIL, NIL, NIL, pClose, pClobber, NIL, false);
- wh := GetWDHandler(theDialog);
- wh^^.whEvent := pEvent;
- END;
-
- { Remove a dialog and its handler}
-
- PROCEDURE SkelRmveDlog;
-
- BEGIN
- SkelRmveWind(theDialog);
- END;
-
- { -------------------------------------------------------------------- }
- { Miscellaneous interface routines }
- { -------------------------------------------------------------------- }
-
-
- {}
- { Override the default sizing limits for a window, or, if theWind}
- { is nil, reset the default limits used by SkelWindow.}
-
- PROCEDURE SkelGrowBounds;
-
- VAR
- h : WHandlerHnd;
- r : Rect;
-
- BEGIN
- IF theWind <> NIL THEN
- SetRect(growRect, hLo, vLo, hHi, vHi)
- ELSE
- BEGIN
- h := GetWHandler(theWind);
- IF h <> NIL THEN
- BEGIN
- SetRect(r, hLo, vLo, hHi, vHi);
- h^^.whGrow := r;
- END;
- END;
- END;
-
- { Set the event mask.}
-
- PROCEDURE SkelEventMask;
-
- BEGIN
- eventMask := mask;
- END;
-
- { Return the event mask.}
-
- PROCEDURE SkelGetEventMask;
-
- BEGIN
- mask := eventMask;
- END;
-
- { Install a background task. If p is nil, the current task is}
- { disabled.}
-
- PROCEDURE SkelBackground;
-
- BEGIN
- pBkgnd := p;
- END;
-
- { Return the current background task. Return nil if none.}
-
- PROCEDURE SkelGetBackground;
- BEGIN
- p := pBkgnd;
- END;
-
- { Install an event-inspecting hook. If p is nil, the hook is}
- { disabled.}
-
- PROCEDURE SkelEventHook;
-
- BEGIN
- pEvent := p;
- END;
-
- PROCEDURE SkelGetEventHook;
-
- BEGIN
- p := pEvent;
- END;
-
- { Set the mask for event types that will be passed to dialogs.}
- { Bit 1 is always set, so that null events will be passed.}
-
- PROCEDURE SkelDlogMask;
-
- BEGIN
- dlogEventMask := BitOr(mask, 1);
- END;
-
- { Return the current dialog event mask.}
-
- PROCEDURE SkelGetDlogMask;
-
- BEGIN
- mask := dlogEventMask;
- END;
-
-
-
-
-
-
-
- END.